<template>
  <div class="chatroom">
    <!-- 聊天记录滚动区域 -->
    <div ref="scrollContainer" class="chatroom__scroll">
      <div class="chatroom__inner">
        <div v-if="hasMore" class="load-more">
          <button class="load-more__btn" :disabled="isLoadingHistory" @click="loadMore">{{ isLoadingHistory ? '加载中...' : '加载更多' }}</button>
        </div>
        <ChatMessage
          v-for="(m, idx) in messages"
          :key="m.id ?? idx"
          :role="m.role"
          :content="m.content"
          :type="m.type"
          :size="m.size"
          :is-history="m.isHistory"
        />
      </div>
    </div>

    <!-- 固定的用户输入区域 -->
    <div class="chatroom__input">
      <div class="composer">
        <textarea
          ref="textareaEl"
          v-model="userInput"
          class="composer__textarea"
          :disabled="isStreaming"
          rows="1"
          :placeholder="placeholderText"
          @input="autoResize"
          @keydown.enter.exact.prevent="onSend"
          @keydown.shift.enter.stop
        />
        <button type="button" class="composer__send" :disabled="!canSend" @click="onSend" aria-label="发送">
          <svg viewBox="0 0 24 24" width="18" height="18" aria-hidden="true">
            <path fill="currentColor" d="M4 12l1.41 1.41L11 7.83V20h2V7.83l5.59 5.58L20 12l-8-8-8 8z"/>
          </svg>
        </button>
      </div>
      <div v-if="isStreaming" class="input__hint">正在生成中，可随时停止</div>
    </div>
  </div>
</template>

<script setup>
import { ref, nextTick, computed, onMounted, watch } from 'vue';
import { useRoute,useRouter } from 'vue-router';
import ChatMessage from '../components/ChatMessage.vue';
import { chatWithSSE } from '../services/sse.js';
import { chatApi } from '../services/chat.js';
import { useConversationStore } from '../stores/conversation';
import { useUserStore } from '../stores/user.js';

const conversationStore = useConversationStore();
const userStore = useUserStore();

const route = useRoute();
//路由跳转（路由器）
const router = useRouter();
const chatId = computed(() => route.query.chatId || 0);

const messages = ref([]);

const userInput = ref('');
const placeholderText = '请输入你的问题，例如：散华的武器选择？';
const isStreaming = ref(false);
const scrollContainer = ref(null);
let closeStream = null;

const canSend = computed(
  () => !isStreaming.value && userInput.value.trim().length > 0
);


// 历史加载状态
const isLoadingHistory = ref(false);
const hasMore = ref(false);
let historyCursor = null; // 游标：已加载历史消息中创建时间最早的那个，用于查询更多历史消息

// 优化滚动行为：平滑滚动到底部
function scrollToBottom() {
  nextTick(() => {
    if (scrollContainer.value) {
      scrollContainer.value.scrollTo({
        top: scrollContainer.value.scrollHeight,
        behavior: 'smooth'
      });
    }
  });
}

// 监听消息变化，自动滚动到底部（仅当新增是末尾追加时）
watch(messages, () => {
  nextTick(() => {
    //如果是加载更多消息则无需自动滚动到底部
    if(!hasMore){
      scrollToBottom();
    }
  });
}, { deep: true });

const textareaEl = ref(null);

function autoResize() {
  const el = textareaEl.value;
  if (!el) return;
  el.style.height = 'auto';
  const max = 160; // 最大高度 160px 左右
  el.style.height = Math.min(el.scrollHeight, max) + 'px';
}

function mapRecordToMessage(rec) {
  return {
    id: rec.id,
    role: rec.messageType === 'user' ? 'user' : 'assistant',
    content: rec.message || '',
    type: rec.messageType,//消息类型
    size: rec.size,
    createTime: rec.createTime, // 保留原始创建时间字符串，例如 "2025-08-20 08:25:38"
    isHistory: true // 标记为历史消息
  };
}

/**
 * 获取消息记录中创建时间最早的原始时间字符串（YYYY-MM-DD HH:mm:ss）
 * 说明：后端返回的时间格式是 "YYYY-MM-DD HH:mm:ss"，该格式可直接进行字符串字典序比较。
 * @param {Array<{createTime?: string}>} records 消息记录数组或消息数组
 * @returns {string|null} 最早的创建时间字符串，如果没有有效时间则返回null
 */
function getOldestCreateTime(records) {
  if (!records || records.length === 0) return null;
  let minStr = null;
  for (const r of records) {
    const s = r && r.createTime ? String(r.createTime).trim() : '';
    if (!s) continue;
    // 字符串直接比较即可（YYYY-MM-DD HH:mm:ss）
    if (minStr === null || s < minStr) minStr = s;
  }
  return minStr;
}

/**
 * 按照对话记录的创建时间升序排序，例如：8.1，8.4，8.12
 * @param records 
 */
function sortAscByCreateTime(records) {
  return [...records].sort((a, b) => {
    const sa = a && a.createTime ? String(a.createTime) : '';
    const sb = b && b.createTime ? String(b.createTime) : '';
    if (sa === sb) return 0;
    return sa < sb ? -1 : 1;
  });
}

/**
 * 发送请求，查询历史对话记录
 */
async function loadInitialHistory() {
  if (!chatId.value) return;
  isLoadingHistory.value = true;
  try {
    const { records, hasMore: more, lastCreateTime } = await chatApi.listChatHistory(chatId.value, 10);
    const asc = sortAscByCreateTime(records).map(mapRecordToMessage);
    messages.value = asc;
    //打印对话历史，便于调试
    // messages.value.forEach((element, i) => {
    //   console.log(element)
    // })
    hasMore.value = !!more;
    // 设置游标为已加载消息中创建时间最早的
    historyCursor = getOldestCreateTime(messages.value);
  } catch (e) {
    console.error('加载历史失败', e);
  } finally {
    isLoadingHistory.value = false;
  }
}

/**
 * 加载更多消息
 */
async function loadMore() {
  if (!chatId.value || isLoadingHistory.value || !hasMore.value) return;
  isLoadingHistory.value = true;
  try {
    const { records, hasMore: more, lastCreateTime } = await chatApi.listChatHistory(chatId.value, 10, historyCursor);
    const asc = sortAscByCreateTime(records).map(mapRecordToMessage);
    messages.value = [...asc, ...messages.value];
    hasMore.value = !!more;
    // 更新游标为当前已加载消息中创建时间最早的
    historyCursor = getOldestCreateTime(messages.value);
  } catch (e) {
    console.error('加载更多历史失败', e);
  } finally {
    isLoadingHistory.value = false;
  }
}

/**
 * 发送用户消息给后端，与 AI 进行对话
 */
function onSend() {
  const text = userInput.value.trim();
  if (!text || isStreaming.value) return;

  // 用户消息（立即本地显示）
  messages.value.push({ role: 'user', content: text, isHistory: false });
  userInput.value = '';
  autoResize();

  // 助手占位，开启流式
  const assistantMsg = { role: 'assistant', content: '', isHistory: false };
  messages.value.push(assistantMsg);
  isStreaming.value = true;
  
  closeStream = chatWithSSE(
    {
      chatId: chatId.value || undefined,
      userMessage: text,
      messageType: 'user'
    },
    {
      onOpen: () => {},
      onMessage: (chunk) => {
        assistantMsg.content += chunk ?? '';
       
      },
      // 插入 PDF 消息
      onPdf: (payload) => {
        let fileUrl = '';
        let fileSize;
        try {
          const obj = JSON.parse(String(payload));
          fileUrl = obj?.url ?? '';
          fileSize = obj?.size;
        } catch (_) {
          fileUrl = String(payload || '');
        }
        const safeUrl = fileUrl.trim();
        if (!safeUrl) return;
        messages.value.push({ role: 'assistant', type: 'SEND_PDF_FILE', content: safeUrl, size: fileSize, isHistory: false });
      },
      // 插入一个新的抽卡分析消息
      onCardDrawing: (data) => {
        messages.value.push({ role: 'assistant', type: 'SEND_CARD_DRAWING_ANALYSIS', content: data });
      },
      /**
       * 新增会话
       * 注意：将回调函数改为 async 异步函数,使用 await 等待 conversationStore.loadConversations (uid) 
       * 完成后再执行后续操作
       * @param data 
       */
      onAddNewConversation: async (data) => {
        const uid = userStore.currentUser?.id || userStore.currentUser?.userId;
        if (uid) {
          await conversationStore.loadConversations(uid);
          console.log("重新加载对话历史列表")
        }
        //去除双引号 ""，防止后端在类型转换时（转换成Long）出现问题
        const chatId = data.replace(/"/g, '');
        //等待路由跳转完成
        await router.push({
          path: '/',
          query: { chatId: chatId }
        });
      },
      onComplete: () => {
        isStreaming.value = false;
        closeStream?.();
        closeStream = null;
        scrollToBottom();
      },
      onError: (err) => {
        if (!assistantMsg.content) {
          assistantMsg.content = `[发生错误] ${err?.message ?? ''}`;
        }
        isStreaming.value = false;
        closeStream?.();
        closeStream = null;
      },
    }
  );
}

onMounted(() => {
  if (chatId.value) {
    loadInitialHistory();
  }else{
    //用户首次进入聊天界面，没有chatId，开启新对话，并提供一个友好的助手消息
    messages.value = [{ 
        role: 'assistant', 
        content: "你好，我是鸣潮游戏攻略助手。可以向我询问角色武器选择、声骸搭配、角色配队等问题；"
                  +"我还可以将攻略保存到PDF文件中、对你游戏中的抽卡结果进行分析。"
      }]
  }
});

// 监听路由变化，切换会话时重新加载历史
watch(() => route.fullPath, () => {
  messages.value = [];
  hasMore.value = false;
  historyCursor = null;
  if (chatId.value) {
    loadInitialHistory();
  }else{
    //切换会话时，如果没有chatId，说明是一个新对话，给一个友好的助手消息
    messages.value = [{ 
        role: 'assistant', 
        content: "你好，我是鸣潮游戏攻略助手。可以向我询问角色武器选择、声骸搭配、角色配队等问题；"
                  +"我还可以将攻略保存到PDF文件中、对你游戏中的抽卡结果进行分析。"
      }]
  }
});
</script>

<style scoped>
.chatroom { 
  height: calc(100vh); 
  display: flex;
  flex-direction: column;
  overflow: hidden; /* 防止整个页面滚动 */
}

/* 聊天记录滚动区域 */
.chatroom__scroll { 
  flex: 1;
  overflow-y: auto; 
  overflow-x: hidden;
  background: var(--page-bg);
  /* 优化滚动条样式 */
  scrollbar-width: thin;
  scrollbar-color: #d7dbe0 transparent;
}

.chatroom__scroll::-webkit-scrollbar {
  width: 8px;
}

.chatroom__scroll::-webkit-scrollbar-track {
  background: transparent;
}

.chatroom__scroll::-webkit-scrollbar-thumb {
  background: #d7dbe0;
  border-radius: 4px;
}

.chatroom__scroll::-webkit-scrollbar-thumb:hover {
  background: #c1c5c9;
}

.chatroom__inner { 
  max-width: var(--page-max-width); 
  margin: 0 auto; 
  padding: 24px 16px 24px; /* 减少底部padding，因为输入框现在是固定的 */
}

.load-more { text-align: center; margin-bottom: 12px; }
.load-more__btn { 
  padding: 6px 12px; border-radius: 8px; border: 1px solid var(--border-color); 
  background: #fff; cursor: pointer; font-size: 13px; color: var(--text-primary);
}
.load-more__btn:disabled { opacity: .6; cursor: not-allowed; }

/* 固定的用户输入区域 */
.chatroom__input {
  flex-shrink: 0; /* 防止输入框被压缩 */
  background: #f7f8fa;
}

.composer {
  max-width: var(--page-max-width);
  margin: 0 auto;
  position: relative;
  padding: 12px 16px 16px;
}

.composer::before {
  content: '';
  position: absolute;
  left: 16px; right: 16px; top: 12px; bottom: 16px;
  border: 1px solid var(--border-color);
  border-radius: 24px;
  background: #fff;
  z-index: 0;
  pointer-events: none; /* 背景不拦截点击 */
}

.composer__textarea {
  position: relative;
  z-index: 1;
  width: 100%;
  min-height: 78px;
  max-height: 160px;
  padding: 14px 56px 14px 18px;
  border: none;
  outline: none;
  background: transparent;
  resize: none;
  font-size: 14px;
  line-height: 1.6;
  color: var(--text-primary);
}

.composer__textarea::placeholder { 
  color: #c0c4cc; 
}

.composer__textarea:disabled { 
  color: #9aa0a6; 
}

.composer__send {
  position: absolute; 
  right: 24px; 
  bottom: 22px;
  width: 36px; 
  height: 36px; 
  border-radius: 50%;
  border: none; 
  background: #e5e7eb; 
  color: #6b7280; 
  cursor: pointer;
  display: inline-flex; 
  align-items: center; 
  justify-content: center;
  z-index: 1; /* 保证在背景之上可点击 */
  transition: all 0.2s ease;
}

.composer__send:enabled { 
  background: #111827; 
  color: #fff; 
}

.composer__send:enabled:hover {
  background: #374151;
  transform: scale(1.05);
}

.composer__send:disabled { 
  cursor: not-allowed; 
  opacity: .7; 
}

.input__hint { 
  max-width: var(--page-max-width); 
  margin: 4px auto 0; 
  padding: 0 16px; 
  color: var(--text-secondary); 
  font-size: 12px; 
}

/* 响应式设计 */
@media (max-width: 768px) {
  .chatroom__inner {
    padding: 16px 12px 16px;
  }
  
  .composer {
    padding: 8px 12px 12px;
  }
  
  .composer__textarea {
    padding: 12px 48px 12px 14px;
  }
  
  .composer__send {
    right: 20px;
    bottom: 18px;
    width: 32px;
    height: 32px;
  }
}
</style>

